﻿using System.Collections.Generic;
using SimpleWorkflow.Data;
using SimpleWorkflow.Steps;
using SimpleWorkflow.Patterns;

namespace SimpleWorkflow.Core
{
    public delegate void StepExecuted(ISimpleStep step);

    public class SimpleFlow<T> : ISimpleFlow where T : ISharedFlowContext
    {
        public const string SharedContext = "__SharedContext";
        public event StepExecuted StepExecuted;
        public delegate void RunProxyDelegate(ISimpleStep step);

        private SimpleStep<T> Root { get; set; }
        public FlowContext WorkflowContext { get; private set; }

        public SimpleFlow(Segment pattern)
        {
            WorkflowContext = new FlowContext();
            Root = new Generator<T>(WorkflowContext, Execute).FromSegment(pattern);
        }

        public void Run(Dictionary<string, object> inputs, ISharedFlowContext sharedContext)
        {
            if (inputs != null)
                foreach (var input in inputs)
                    WorkflowContext.AddAndSetValue(new SimpleReference(input.Key), input.Value);

            if (!Equals(sharedContext, null))
            {
                sharedContext.WorkflowContext = WorkflowContext;
                WorkflowContext.AddAndSetValue(new SimpleReference(SharedContext), sharedContext);
            }

            Run();
        }

        public void Run(Dictionary<string, object> inputs)
        {
            Run(inputs, default(T));
        }

        public void Run()
        {
            Execute(Root);
        }

        private void Execute(ISimpleStep step)
        {
            // do other stuff like exception handling, logging what was run, etc
            step.Run();

            if (StepExecuted != null)
                StepExecuted(step);
        }
    }
}
